//
//  WCCoreDataStore.m
//  WC
//
//  Created by 杨鑫 on 15/5/6.
//  Copyright (c) 2015年 智康. All rights reserved.
//

#import "WCCoreDataStore.h"
//
#import "NSDate+Utilities.h"
#import "NSString+Utilities.h"
#import "WoundRecord.h"
@import CoreData;

@interface WCCoreDataStore ()


@property (strong, nonatomic) NSManagedObjectModel *model;

@end

@implementation WCCoreDataStore

#pragma mark - Create

+ (instancetype)shareStore
{
    static WCCoreDataStore *store = nil;
    //block
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        store = [[WCCoreDataStore alloc] initPrivate];
    });
    return store;
}

- (instancetype)init
{
    @throw [NSException exceptionWithName:@"Singleton"
                                   reason:@"Use + [WCCoreDataStore shareStore]"
                                 userInfo:nil];
    return nil;
}


- (instancetype)initPrivate
{
    self = [super init];
    if (self) {
        //创建模型，被协调器使用
        _model = [[NSManagedObjectModel alloc] initWithContentsOfURL:[[NSBundle mainBundle] URLForResource:@"WCNModels" withExtension:@"momd"]];
        
        //(持久化协调器)创建协调器, 直接操作存储文件的对象
        NSPersistentStoreCoordinator *psc = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:_model];
        NSURL *storeURL = [NSURL fileURLWithPath:[self path]];
        
        NSError *error = nil;
        
        NSString *verson = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"];
        NSString *localVerson = [[NSUserDefaults standardUserDefaults] valueForKey:@"localVerson"];
        
        if([[NSFileManager defaultManager] fileExistsAtPath:[self path]] && ![verson isEqualToString:localVerson]){//如果不存在,则说明是第一次运行这个程序，那么建立这个文件夹
            NSString *docs = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
            NSString *path1 = [docs stringByAppendingPathComponent:@"coreDataDemo.sqlite"];
            NSString *path2 = [docs stringByAppendingPathComponent:@"coreDataDemo.sqlite-shm"];
            NSString *path3 = [docs stringByAppendingPathComponent:@"coreDataDemo.sqlite-wal"];
            [[NSFileManager defaultManager] removeItemAtPath:path1 error:&error];
            [[NSFileManager defaultManager] removeItemAtPath:path2 error:&error];
            [[NSFileManager defaultManager] removeItemAtPath:path3 error:&error];
            [[NSUserDefaults standardUserDefaults] setObject:verson forKey:@"localVerson"];
        }
        #warning CoreData 升级带来的crash问题
        //要考虑到，core data随着app升级以后,实体被修改的问题
        NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                                 [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
                                 [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
        
//        错误处理
        if (![psc addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]) {
            NSLog(@"%@",error);
            @throw [NSException exceptionWithName:@"OpenFailure" reason:[error localizedDescription] userInfo:nil];
        }
//
        //创建上下文，调用协调器
        _context = [[NSManagedObjectContext alloc] init];
        _context.persistentStoreCoordinator = psc;
    }
    return self;
}

#pragma mark - Account
//储存账户
- (Account *)createAccount:(NSDictionary *)data
{
    Account *ac = [self createEntity:@"Account" insert:YES];
    [ac safeSetValuesForKeysWithDictionary:data];
    
    return ac;
}
//更新账户
- (AccountStat *)updateAccountStat:(NSDictionary *)stat;
{
    AccountStat *oldStat = [self findOneEntity:@"AccountStat" withPredicate:nil];
    if (oldStat) {
        [self.context deleteObject:oldStat];
    }
    
    AccountStat *newStat = [self createEntity:@"AccountStat" insert:YES];
    [newStat safeSetValuesForKeysWithDictionary:stat];
    
    return newStat;
}

- (AccountService *)updateAccountService:(NSDictionary *)service
{
    AccountService *oldService = [self findOneEntity:@"AccountService" withPredicate:nil];
    if (oldService) {
        [self.context deleteObject:oldService];
    }
    
    AccountService *newService = [self createEntity:@"AccountService" insert:YES];
    [newService safeSetValuesForKeysWithDictionary:service];
    NSArray *serviceConfigs = [self insertEntity:@"AccountServiceConfig" withArray:service[@"serviceConfigs"] overWrite:NO predicate:nil sort:nil];
    [newService addConfigs:[NSSet setWithArray:serviceConfigs]];
    
    return newService;
}

- (Account *)getAccount
{
    return [self findOneEntity:@"Account" withPredicate:nil];
}

- (AccountStat *)getAccountStat
{
    return [self findOneEntity:@"AccountStat" withPredicate:nil];
}

- (AccountServiceEntity *)getAccountService
{
    AccountService *service = [self findOneEntity:@"AccountService" withPredicate:nil];
    AccountServiceEntity *serviceEntity = [[AccountServiceEntity alloc] init];
//    serviceEntity.serviceArea = service.serviceArea;
//    serviceEntity.serviceRadius = service.serviceRadius;
    serviceEntity.serviceConfigs = [NSMutableArray array];
    
    NSArray *serviceConfigs = [service allServiceConfigs];
    if (serviceConfigs && serviceConfigs.count > 0) {
        
        for (AccountServiceConfig *serviceConfig in serviceConfigs) {
            AccountServiceConfigEntity *serviceConfigEntity = [[AccountServiceConfigEntity alloc] init];
            serviceConfigEntity.isEnabled = serviceConfig.isEnabled;
            serviceConfigEntity.price = [serviceConfig.price doubleValue];
            serviceConfigEntity.nursingType = serviceConfig.nursingType;
            serviceConfigEntity.serviceNote = serviceConfig.serviceNote;
            serviceConfigEntity.serviceRadius =[serviceConfig.serviceRadius longValue];
          [serviceEntity.serviceConfigs addObject:serviceConfigEntity];
        }
       
    } else {
        AccountServiceConfigEntity *serviceConfigEntity = [[AccountServiceConfigEntity alloc] init];
        serviceConfigEntity.isEnabled = NO;
        serviceConfigEntity.price = .0;
        serviceConfigEntity.nursingType = @"暂无配置";
        serviceConfigEntity.serviceNote =@"";
        [serviceEntity.serviceConfigs addObject:serviceConfigEntity];
    }
    
    return serviceEntity;
}

#pragma mark - Patient
//储存过往病人
- (NSArray *)createHistoryPatients:(NSArray *)data save:(BOOL)save
{
    if (save) {
        return [self insertEntity:@"HistoryPatient" withArray:data overWrite:YES predicate:nil sort:nil];
    } else {
        NSMutableArray *patients = [NSMutableArray array];
        for (NSDictionary *dataItem in data) {
            NSEntityDescription *entity = [NSEntityDescription entityForName:@"HistoryPatient" inManagedObjectContext:self.context];
            HistoryPatient *managedEntity = [[HistoryPatient alloc] initWithEntity:entity insertIntoManagedObjectContext:nil];
            [managedEntity safeSetValuesForKeysWithDictionary:dataItem];
            
            [patients addObject:managedEntity];
        }
        
        return [patients copy];
    }
}

- (NSArray *)getHistoryPatients
{
    NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"localUpdateTime" ascending:YES];
    NSArray *patients = [self findAllEntity:@"HistoryPatient" withSort:@[sort] withPredicate:nil];
    
    return patients;
}

- (NSArray *)createPatients:(NSArray *)data
{
    [self insertEntity:@"Patient" withArray:data overWrite:YES predicate:nil sort:nil];
    return [self getPatients];
}

- (Patient *)createPatient:(NSDictionary *)data save:(BOOL)save
{
    Patient *patient = [self createEntity:@"Patient" insert:save];
    if (data) {
        [patient safeSetValuesForKeysWithDictionary:data];
    }
    return patient;
}

- (NSArray *)getPatients
{
    //根据床位排序
    NSSortDescriptor * sort = [NSSortDescriptor sortDescriptorWithKey:@"stringId" ascending:YES];
    return [self findAllEntity:@"Patient" withSort:@[sort] withPredicate:nil];
    //return patients;
//    //根据床位排序
//    return [patients sortedArrayUsingComparator:^(Patient *patient1, Patient *patient2){
//        NSInteger value = [patient1.stringId integerValue] - [patient2.stringId integerValue] ;
//        if (value > 0) {
//            return NSOrderedAscending;
//        } else if (value < 0) {
//            return NSOrderedDescending;
//        }
//        return NSOrderedSame;
//    }];
}

- (void)updateIdPatient:(id)patient withData:(NSDictionary *)data
{
    NSManagedObject *managedObject = (NSManagedObject *)patient;
    [managedObject safeSetValuesForKeysWithDictionary:data];
    
    NSSet *oldNurseMembers = [patient valueForKey:@"nurseMembers"];
    if (oldNurseMembers && oldNurseMembers.count > 0) {
        [patient setValue:nil forKey:@"mainNurse"];
        [patient setValue:[NSSet set] forKey:@"nurseMembers"];
        for (Nurse *nurse in oldNurseMembers) {
            [self.context deleteObject:nurse];
        }
    }
    
    NSArray *nurseMembers = [self insertEntity:@"Nurse" withArray:data[@"nurseMembers"] overWrite:NO predicate:nil sort:nil];
    if (nurseMembers &&nurseMembers.count>0) {
        [patient setValue:nurseMembers[0] forKey:@"mainNurse"];
    }
 
    NSMutableArray *mutableNurseMembers = [NSMutableArray arrayWithArray:nurseMembers];
    [mutableNurseMembers removeObjectAtIndex:0];
    [patient setValue:[NSSet setWithArray:mutableNurseMembers] forKey:@"nurseMembers"];
}

- (NSArray *)createPatientSchemes:(NSArray *)data withRecord:(NSString *)recordId
{
    return [self insertEntity:@"PatientScheme" withArray:data overWrite:YES predicate:[NSPredicate predicateWithFormat:@"recordId = %@", recordId] sort:nil];
}

- (PatientScheme *)createPatientScheme
{
    return [self createEntity:@"PatientScheme" insert:NO];
}
//案列(方案)
- (NSArray *)getPatientSchemes:(NSString *)recordId
{
    NSArray *patients = [self findAllEntity:@"PatientScheme" withSort:nil withPredicate:[NSPredicate predicateWithFormat:@"recordId = %@ && status = 'IN_PROGRESS'", recordId]];
    //进行升序排列
    return [patients sortedArrayUsingComparator:^(PatientScheme *patient1, PatientScheme *patient2){
        NSInteger value = [patient1.stringId integerValue] - [patient2.stringId integerValue] ;
        if (value > 0) {
            return NSOrderedDescending;
        } else if (value < 0) {
            return NSOrderedAscending;
        }
        return NSOrderedSame;
    }];
}

#pragma mark - Comment

- (NSArray *)createComments:(NSArray *)data save:(BOOL)save
{
    if (save) {
        return [self insertEntity:@"Comment" withArray:data overWrite:YES predicate:nil sort:nil];
    } else {
        NSMutableArray *comments = [NSMutableArray array];
        for (NSDictionary *dataItem in data) {
            NSEntityDescription *entity = [NSEntityDescription entityForName:@"Comment" inManagedObjectContext:self.context];
            HistoryPatient *comment = [[HistoryPatient alloc] initWithEntity:entity insertIntoManagedObjectContext:nil];
            [comment safeSetValuesForKeysWithDictionary:dataItem];
            
            [comments addObject:comment];
        }
        
        return [comments copy];
    }
}

- (NSArray *)getComments
{
    NSArray *comments = [self findAllEntity:@"Comment" withSort:nil withPredicate:nil];
    
    return [comments sortedArrayUsingComparator:^(Comment *patient1, Comment *patient2){
        NSDate *date1 = [NSDate dateWithString:patient1.commentTime byFormat:@"yyyy-MM-dd HH:mm:ss"], *date2 = [NSDate dateWithString:patient2.commentTime byFormat:@"yyyy-MM-dd HH:mm:ss"];
        
        return [date1 compare:date2];
    }];
}

#pragma mark - Orders

//- (NSArray *)createOrders:(NSArray *)data withCategory:(int)category save:(BOOL)save
//{
//    if (save) {
//        NSMutableArray *muList = [NSMutableArray array];
//        for (NSDictionary *item in data) {
//            NSMutableDictionary *muItem = [NSMutableDictionary dictionaryWithDictionary:item];
//            muItem[@"category"] = @(category);
//            [muList addObject:muItem];
//        }
//        return [self insertEntity:@"Order" withArray:muList overWrite:YES withPredicate:[NSPredicate predicateWithFormat:@"category = %d", category]];
//    } else {
//        NSMutableArray *orders = [NSMutableArray array];
//        for (NSDictionary *item in data) {
//            NSMutableDictionary *muItem = [NSMutableDictionary dictionaryWithDictionary:item];
//            muItem[@"category"] = @(category);
//            
//            NSEntityDescription *entity = [NSEntityDescription entityForName:@"Order" inManagedObjectContext:self.context];
//            Order *order = [[Order alloc] initWithEntity:entity insertIntoManagedObjectContext:nil];
//            
//            [order safeSetValuesForKeysWithDictionary:muItem];
//            
//            [orders addObject:order];
//        }
//        return [orders copy];
//    }
//}

//- (NSArray *)getOrdersByCategory:(int)category
//{
//    NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"localUpdateTime" ascending:YES];
//    return [self findAllEntity:@"Order" withSort:@[sort] withPredicate:[NSPredicate predicateWithFormat:@"category = %d", category]];
//}

//- (void)updateOrder:(Order *)order withData:(NSDictionary *)data
//{
//    [order safeSetValuesForKeysWithDictionary:data];
//}

#pragma mark - OrderComment

- (OrderComment *)createOrderComment:(NSDictionary *)data save:(BOOL)save
{
    OrderComment *vo = [self createEntity:@"OrderComment" insert:save];
    [vo safeSetValuesForKeysWithDictionary:data];
    
    return vo;
}

- (OrderComment *)getOrderCommentById:(NSString *)commentId
{
    return [self findOneEntity:@"OrderComment" withPredicate:[NSPredicate predicateWithFormat:@"stringId = %@", commentId]];
}

#pragma mark - Other

- (BOOL)saveData
{
    //一般插入时，马上保存一次；
    //其他更新操作，只在app后台运行时才保存
    
    NSError *error;
    BOOL success = [self.context save:&error];
    if (!success) {
        [NSException raise:@"Fetch fialed" format:@"Reason: %@", [error localizedDescription]];
    }
    return success;
}

- (void)removeAllData
{
    [self saveData];
    
    NSPersistentStoreCoordinator *psc = _context.persistentStoreCoordinator;
    NSArray *stores = [psc persistentStores];
    for(NSPersistentStore *store in stores) {
        [psc removePersistentStore:store error:nil];
        [[NSFileManager defaultManager] removeItemAtPath:store.URL.path error:nil];
    }
    
    NSURL *storeURL = [NSURL fileURLWithPath:[self path]];
    NSError *error = nil;
    if (![psc addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
        @throw [NSException exceptionWithName:@"OpenFailure" reason:[error localizedDescription] userInfo:nil];
    }
}

#pragma mark - Private

- (id)createEntity:(NSString *)name insert:(BOOL)insert
{
    NSEntityDescription *entity = [NSEntityDescription entityForName:name inManagedObjectContext:self.context];
    NSManagedObject *managedEntity = [[NSManagedObject alloc] initWithEntity:entity insertIntoManagedObjectContext:insert?self.context:nil];
    
    return managedEntity;
}

- (NSArray *)insertEntity:(NSString *)name withArray:(NSArray *)list overWrite:(BOOL)is predicate:(NSPredicate *)predicate sort:(NSArray *)sort
{
    if (is) {
        //删除原来的数据
        NSArray *oldList = [self findAllEntity:name withSort:sort withPredicate:predicate];
        for (NSManagedObject *entity in oldList) {
            [self.context deleteObject:entity];
        }
    }
    
    NSMutableArray *entities = [[NSMutableArray alloc] init];
    for (NSDictionary *item in list) {

        NSManagedObject *entity = [NSEntityDescription insertNewObjectForEntityForName:name inManagedObjectContext:self.context];
        
        [entity safeSetValuesForKeysWithDictionary:item];
        
        [entities addObject:entity];
    }
    
    #warning save之后被删除的实体就不能被修改，否则应用会崩溃.
    //可以通过注释下面这句代码来解决，主要是save之后被删除的实体对象就不能使用了。
//    [self saveData];
    
    return entities;
}

- (NSArray *)findAllEntity:(NSString *)name withSort:(NSArray *)sorts withPredicate:(NSPredicate *)predicate
{
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    request.entity = [NSEntityDescription entityForName:name inManagedObjectContext:self.context];
    request.predicate = predicate;
    
//    if (!sorts) {
//        NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"stringId" ascending:YES];
//        sorts = @[sort];
//    }
    request.sortDescriptors = sorts;
    
    NSError *error;
    NSArray *result = [self.context executeFetchRequest:request error:&error];
    if (!result) {
        [NSException raise:@"Fetch fialed" format:@"Reason: %@", [error localizedDescription]];
        return nil;
    }
    //result好像会弱引用查询的结果，save的时候使用
    return result;
}

- (id)findOneEntity:(NSString *)name withPredicate:(NSPredicate *)predicate
{
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    request.entity = [NSEntityDescription entityForName:name inManagedObjectContext:self.context];
    request.predicate = predicate;
    
    NSError *error;
    NSArray *result = [self.context executeFetchRequest:request error:&error];
    if (!result) {
        [NSException raise:@"Fetch fialed" format:@"Reason: %@", [error localizedDescription]];
        return nil;
    }
    
    if (result.count > 0) {
        return result[0];
    } else {
        return nil;
    }
}

#pragma ---------------------------新增-----------------------
- (NSArray *)cwqInsertWithEntity:(NSString *)name array:(NSArray *)list overWrite:(BOOL)is predicate:(NSPredicate *)predicate sort:(NSArray *)sort {

    if (is) {
        //删除原来的数据
        NSArray *oldList = [self findAllEntity:name withSort:sort withPredicate:predicate];
        for (NSManagedObject *entity in oldList) {
            [self.context deleteObject:entity];
        }
    }
    
//    NSMutableArray *entities = [[NSMutableArray alloc] init];
    for (NSDictionary *item in list) {
        
        WoundRecord *entity = (WoundRecord *)[NSEntityDescription insertNewObjectForEntityForName:@"WoundRecord" inManagedObjectContext:self.context];
        [entity safeSetValuesForKeysWithDictionary:item];
//        [entities addObject:entity];
    }
    NSArray *entities = [self findAllEntity:name withSort:sort withPredicate:predicate];
    return entities;

}

- (NSArray *)cwqFindWithEntity:(NSString *)name sort:(NSArray *)sorts predicate:(NSPredicate *)predicate pageSize:(NSInteger)pageSize currentCount:(NSInteger)currentCount
{
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    request.entity = [NSEntityDescription entityForName:name inManagedObjectContext:self.context];
    request.predicate = predicate;
    
    // 限定查询结果的数量
    //setFetchLimit
    // 查询的偏移量
    //setFetchOffset
    
    ////每次要取多少条数据，10就是每次从数据库读取10条数据
    [request setFetchLimit:pageSize];
    
    /*   //从数据库里每次加载500条数据来筛选数据
     [request setFetchBatchSize:10];
     */
    //读取数据库的游标偏移量，从游标开始读取数据
    [request setFetchOffset:currentCount];
    
    request.sortDescriptors = sorts;
    
    NSError *error;
    NSArray *result = [self.context executeFetchRequest:request error:&error];
    if (!result) {
        [NSException raise:@"Fetch fialed" format:@"Reason: %@", [error localizedDescription]];
        return nil;
    }
    //result好像会弱引用查询的结果，save的时候使用
    return result;
}


#pragma mark - Path
//文件储存路径
- (NSString *)path
{
    NSString *docs = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
    return [docs stringByAppendingPathComponent:@"coreDataDemo.sqlite"];
    //return [docs stringByAppendingPathComponent:@"wcn.data"];
}




@end
